﻿using System;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.Electric.Common;
using HYElectricKernel;
using HYRElectric.WirePlace;

namespace HYRElectric.Equipment
{
	public class FanLayout : EquipmentLayout
	{
		public FanLayout(UIDocument uiDoc, Document document, DbFamilyObject familyObject, FamilySymbol selectedFamilySymbol, List<BuiltInCategory> lstFilter) : base(uiDoc, document, familyObject, selectedFamilySymbol, lstFilter)
		{
		}

		public override bool Layout()
		{
			if (!base.Layout())
			{
				return false;
			}
			this.form = new FanLayoutForm(this.doc);
			this.form.Show(WindowHelper.HWndRevit);
			WindowHelper.SendMessageToWndRevit();
			for (;;)
			{
				try
				{
					this.startPoint = this.docUI.Selection.PickPoint("请选取圆弧起点");
					this.endPoint = this.docUI.Selection.PickPoint("请选取圆弧终点");
					this.midPoint = this.docUI.Selection.PickPoint("请选取圆弧中间任意一点");
					this.otherPoint = this.docUI.Selection.PickPoint("请选取同心圆弧上任意一点");
					if ((this.midPoint - this.startPoint).IsZeroLength() || (this.endPoint - this.startPoint).IsZeroLength() || (this.endPoint - this.midPoint).IsZeroLength())
					{
						TaskDialog.Show("盈建科提示", "三点不能重合，请选取三个不同点。");
						continue;
					}
					XYZ xyz = (this.midPoint - this.startPoint).Normalize();
					XYZ xyz2 = (this.endPoint - this.midPoint).Normalize();
					if (xyz.IsAlmostEqualTo(xyz2) || xyz.Negate().IsAlmostEqualTo(xyz2))
					{
						TaskDialog.Show("盈建科提示", "三点不能共线。");
						continue;
					}
				}
				catch (Exception)
				{
					break;
				}
				this.centerPoint = null;
				List<Dictionary<XYZ, double>> insertPoints = this.GetInsertPoints();
				if (!this.IsEmptyPointSet(insertPoints))
				{
					TransactionGroup transactionGroup = new TransactionGroup(this.doc, "TransactionGroup");
					try
					{
						transactionGroup.Start();
						Transaction transaction = null;
						try
						{
							foreach (Dictionary<XYZ, double> dictionary in insertPoints)
							{
								FamilyInstance startdevice = null;
								foreach (KeyValuePair<XYZ, double> keyValuePair in dictionary)
								{
									transaction = new Transaction(this.doc, "FanLayout");
									transaction.Start();
									FamilyInstance familyInstance = YJKRevitTools.LayFamilySymbol(this.doc, keyValuePair.Key, this.familySymbol, this.doc.ActiveView.GenLevel, keyValuePair.Value);
									if (familyInstance == null)
									{
										throw new Exception("布置设备出错。");
									}
									base.SetParametersValue(familyInstance, this.dbFamilyObject.Size);
									transaction.Commit();
									if (this.form.LinkLineWay != 0 && (this.form.DislocationWay != 2 || this.form.LinkLineWay != 1))
									{
										if (this.form.LinkLineWay == 2)
										{
                                            NewConnectWire.CreateWire(this.doc, startdevice, familyInstance, (Autodesk.Revit.DB.Electrical.WiringType)0, this.centerPoint);
										}
										else
										{
                                            NewConnectWire.CreateWire(this.doc, startdevice, familyInstance, (Autodesk.Revit.DB.Electrical.WiringType)1, null);
										}
										startdevice = familyInstance;
									}
								}
							}
						}
						catch (Exception)
						{
							if (transaction != null && transaction.GetStatus() != TransactionStatus.Committed)
							{
								transaction.RollBack();
							}
							break;
						}
						transactionGroup.Assimilate();
						continue;
					}
					catch (Exception)
					{
						transactionGroup.RollBack();
						continue;
					}
					break;
				}
			}
			this.form.Close();
			return true;
		}

		private bool IsEmptyPointSet(List<Dictionary<XYZ, double>> pointSet)
		{
			if (pointSet == null || pointSet.Count <= 0)
			{
				return true;
			}
			foreach (Dictionary<XYZ, double> dictionary in pointSet)
			{
				if (dictionary != null && dictionary.Count > 0)
				{
					return false;
				}
			}
			return true;
		}

		private List<Dictionary<XYZ, double>> GetInsertPoints()
		{
			if (this.form == null)
			{
				return null;
			}
			List<Dictionary<XYZ, double>> list = new List<Dictionary<XYZ, double>>();
			this.rCount = this.form.RCount;
			this.cCount = this.form.CCount;
			this.margin = this.form.Margin;
			this.isAutoAngle = this.form.IsAutoAngle;
			this.angle = this.form.Angle;
			if (this.rCount <= 0 || this.cCount <= 0)
			{
				return null;
			}
			Arc arc = this.doc.Application.CreatYJKArc(this.startPoint, this.endPoint, this.midPoint);
			this.centerPoint = arc.Center;
			double radius = arc.Radius;
			double num = Math.Abs(arc.GetYJKEndParameter(1) - arc.GetYJKEndParameter(0));
			this.maxBasePoint = ((arc.Normal.Z < 0.0) ? this.endPoint : this.startPoint);
			double num2 = this.centerPoint.DistanceTo(this.otherPoint);
			this.maxBasePoint = ((num2 < radius) ? this.maxBasePoint : (this.centerPoint + num2 * (this.maxBasePoint - this.centerPoint).Normalize()));
			if (this.rCount == 1 && this.cCount == 1)
			{
				Dictionary<XYZ, double> dictionary = new Dictionary<XYZ, double>();
				XYZ xyz = Geometry.RotateTo(this.centerPoint + 0.5 * (radius + num2) * (this.maxBasePoint - this.centerPoint).Normalize(), this.centerPoint, XYZ.BasisZ, num / 2.0);
				double num3 = XYZ.BasisX.AngleOnPlaneTo(xyz - this.centerPoint, XYZ.BasisZ);
				num3 = (this.isAutoAngle ? (num3 - Math.PI*.5) : ((double)this.angle));
				num3 = AssistFunc.RadianToAngle(num3);
				dictionary.Add(xyz, num3);
				list.Add(dictionary);
				return list;
			}
			this.rSpace = ((Math.Abs(2.0 * this.margin + (double)this.rCount - 1.0) < 1E-06) ? 0.0 : (Math.Abs(radius - num2) / (2.0 * this.margin + (double)this.rCount - 1.0)));
			this.spaceAngle = ((Math.Abs(2.0 * this.margin + (double)this.cCount - 1.0) < 1E-06) ? 0.0 : (num / (2.0 * this.margin + (double)this.cCount - 1.0)));
			List<List<XYZ>> list2 = new List<List<XYZ>>();
			if (this.form.DislocationWay == 2)
			{
				list2 = this.GetInsertPointsOfArc();
			}
			else if (this.form.DislocationWay == 1)
			{
				list2 = this.GetInsertPointsOfRadius();
			}
			else
			{
				list2 = this.GetInsertPointsOfNone();
			}
			foreach (List<XYZ> list3 in list2)
			{
				Dictionary<XYZ, double> dictionary2 = new Dictionary<XYZ, double>();
				foreach (XYZ xyz2 in list3)
				{
					double num4 = XYZ.BasisX.AngleOnPlaneTo(xyz2 - this.centerPoint, XYZ.BasisZ);
					num4 = (this.isAutoAngle ? (num4 - Math.PI*.5) : ((double)this.angle));
					num4 = AssistFunc.RadianToAngle(num4);
					dictionary2.Add(xyz2, num4);
				}
				list.Add(dictionary2);
			}
			return list;
		}

		private List<List<XYZ>> GetInsertPointsOfNone()
		{
			List<List<XYZ>> list = new List<List<XYZ>>();
			if (this.form.LinkLineWay == 2)
			{
				for (int i = 0; i < this.rCount; i++)
				{
					List<XYZ> list2 = new List<XYZ>();
					XYZ pt = this.maxBasePoint + this.rSpace * (this.margin + (double)i) * (this.centerPoint - this.maxBasePoint).Normalize();
					for (int j = 0; j < this.cCount; j++)
					{
						XYZ item = Geometry.RotateTo(pt, this.centerPoint, XYZ.BasisZ, (this.margin + (double)j) * this.spaceAngle);
						list2.Add(item);
					}
					list.Add(list2);
				}
			}
			else
			{
				for (int k = 0; k < this.cCount; k++)
				{
					List<XYZ> list3 = new List<XYZ>();
					XYZ xyz = Geometry.RotateTo(this.maxBasePoint, this.centerPoint, XYZ.BasisZ, (this.margin + (double)k) * this.spaceAngle);
					for (int l = 0; l < this.rCount; l++)
					{
						XYZ item2 = xyz + this.rSpace * (this.margin + (double)l) * (this.centerPoint - xyz).Normalize();
						list3.Add(item2);
					}
					list.Add(list3);
				}
			}
			return list;
		}

		private List<List<XYZ>> GetInsertPointsOfRadius()
		{
			List<List<XYZ>> list = new List<List<XYZ>>();
			if (this.form.LinkLineWay == 2)
			{
				for (int i = 0; i < this.rCount; i++)
				{
					List<XYZ> list2 = new List<XYZ>();
					XYZ pt = this.maxBasePoint + this.rSpace * (this.margin + (double)i) * (this.centerPoint - this.maxBasePoint).Normalize();
					for (int j = 0; j < this.cCount; j += 2)
					{
						XYZ item = Geometry.RotateTo(pt, this.centerPoint, XYZ.BasisZ, (this.margin + (double)j) * this.spaceAngle);
						list2.Add(item);
					}
					list.Add(list2);
				}
				for (int k = 0; k < this.rCount - 1; k++)
				{
					List<XYZ> list3 = new List<XYZ>();
					XYZ pt2 = this.maxBasePoint + this.rSpace * (this.margin + 0.5 + (double)k) * (this.centerPoint - this.maxBasePoint).Normalize();
					for (int l = 1; l < this.cCount; l += 2)
					{
						XYZ item2 = Geometry.RotateTo(pt2, this.centerPoint, XYZ.BasisZ, (this.margin + (double)l) * this.spaceAngle);
						list3.Add(item2);
					}
					list.Add(list3);
				}
			}
			else
			{
				for (int m = 0; m < this.cCount; m += 2)
				{
					List<XYZ> list4 = new List<XYZ>();
					XYZ xyz = Geometry.RotateTo(this.maxBasePoint, this.centerPoint, XYZ.BasisZ, (this.margin + (double)m) * this.spaceAngle);
					for (int n = 0; n < this.rCount; n++)
					{
						XYZ item3 = xyz + this.rSpace * (this.margin + (double)n) * (this.centerPoint - xyz).Normalize();
						list4.Add(item3);
					}
					list.Add(list4);
				}
				for (int num = 1; num < this.cCount; num += 2)
				{
					List<XYZ> list5 = new List<XYZ>();
					XYZ xyz2 = Geometry.RotateTo(this.maxBasePoint, this.centerPoint, XYZ.BasisZ, (this.margin + (double)num) * this.spaceAngle);
					for (int num2 = 0; num2 < this.rCount - 1; num2++)
					{
						XYZ item4 = xyz2 + this.rSpace * (this.margin + 0.5 + (double)num2) * (this.centerPoint - xyz2).Normalize();
						list5.Add(item4);
					}
					list.Add(list5);
				}
			}
			return list;
		}

		private List<List<XYZ>> GetInsertPointsOfArc()
		{
			List<List<XYZ>> list = new List<List<XYZ>>();
			for (int i = 0; i < this.rCount; i++)
			{
				List<XYZ> list2 = new List<XYZ>();
				XYZ pt = this.maxBasePoint + this.rSpace * (this.margin + (double)i) * (this.centerPoint - this.maxBasePoint).Normalize();
				for (int j = 0; j < this.cCount - i; j++)
				{
					XYZ item = Geometry.RotateTo(pt, this.centerPoint, XYZ.BasisZ, (this.margin + 0.5 * (double)i + (double)j) * this.spaceAngle);
					list2.Add(item);
				}
				list.Add(list2);
			}
			return list;
		}

		private FanLayoutForm form;

		private XYZ startPoint;

		private XYZ midPoint;

		private XYZ endPoint;

		private XYZ otherPoint;

		private int rCount;

		private int cCount;

		private double margin;

		private bool isAutoAngle = true;

		private int angle;

		private XYZ centerPoint;

		private XYZ maxBasePoint;

		private double rSpace;

		private double spaceAngle;
	}
}
